#freeslay - by Rafael and Karlisson

#   tileMainWidth
#  |---------|
#   _________
#  /         \    T
# /           \   |
#/             \  |
#\             /  | tileHeight (bom ser multiplo de 2)
# \           /   |
#  \_________/    |
#
#            |-|
#         tileSideWidth

import random
from random import randint
import colors
import pygame


class Tile(object):
    side_width = 4
    main_width = 14
    height = 20

    # esse eh o contrario, dado a coordenada do grid, dizer a posicao do pixel (relatvio a ponta esquerda superior do hexagono)
    @staticmethod
    def get_position(y, x):
        startx = Tile.main_width*x + Tile.side_width*x
        if x%2 == 0:
            starty = Tile.height*y
        else:
            starty = Tile.height*y - Tile.height/2
        return startx, starty




class Grid(object):
	def __init__(self, surface, width, height, gamelogic):
		self.width = width
		self.height = height
		self.surface = surface

		self.sprite_soldier = pygame.image.load('sprites/soldier.gif').convert()
		self.sprite_tower = pygame.image.load('sprites/tower.gif').convert()

		#indica a posicao do mouse em coordenas do grid
		self.current_mouse = (-5,-5)
		# grid eh uma matriz que guarda o que ocorro em cada tile (-1 significa vazio, 0...8 a nacao)
		self.grid = [ [-1 for x in xrange(width)] for y in xrange(height)]
		# -1 significa nada, 1 significa soldado, 2 significa torre
		self.unit = [ [-1 for x in xrange(width)] for y in xrange(height)]

		random.seed()
		for j in xrange(100):
			for i in xrange(len(gamelogic.nations)):
				self.create_area(randint(0, self.height-1), randint(0, self.width-1), 100, i, 20)

		for i in xrange(20):
			self.unit[randint(0, self.height-1)][randint(0, self.width-1)] = 2

		for y in xrange(height):
			for x in xrange(width):
				self.update_tile(y, x)
		pygame.display.flip()

	def tile_is_inside(self, y, x):
		return x >= 0 and y >= 0 and x < self.width and y < self.height

	# dada uma posicao x,y, retornar em q tile esta esse ponto
	def get_position(self, y, x):
		tilex = x/(Tile.side_width + Tile.main_width)
		if x - (tilex*Tile.main_width + Tile.side_width*tilex) <= Tile.main_width:
			if tilex%2 == 0:
				return (tilex, y/Tile.height)
			else:
				return (tilex, (y + Tile.height/2)/Tile.height)
		else:
			if tilex%2 == 1:
				dy = Tile.height/2
				tiley1 = (y+Tile.height/2)/Tile.height
				tiley2 = y/Tile.height
			else:
				dy = 0
				tiley1 = y/Tile.height
				tiley2 = (y+Tile.height/2)/Tile.height
			nx = tilex*Tile.main_width + Tile.side_width*tilex + Tile.main_width
			ny = y - (y+dy)%Tile.height 
			c = (2*(y+dy))/Tile.height
			r = (2*Tile.side_width)
			if c%2 == 0:
				if((x - nx)*Tile.height > r*(y - ny)):
					return (tilex+1, tiley2)
				else:
					return (tilex, tiley1)
			else:
				if((x - nx)*Tile.height < r*(Tile.height - (y - ny))):
					return (tilex, tiley1)
				else:
					return (tilex+1, tiley2)
	



	def draw_frontier(self, y, x, nation, visited):
		if y < 0 or x < 0 or y >= self.height or x >= self.width:
			return
		if (y,x) in visited:
			return
		visited.append((y,x))
		if self.grid[y][x] != nation:
			return
		self.draw_frontier(y+1,x,nation,visited)
		self.draw_frontier(y-1,x,nation,visited)
		self.draw_frontier(y-x%2,x-1,nation,visited)
		self.draw_frontier(y-x%2,x+1,nation,visited)
		self.draw_frontier(y+1-x%2,x-1,nation,visited)
		self.draw_frontier(y+1-x%2,x+1,nation,visited)
		self.update_tile(y,x,True)

	def draw_tile(self, y, x, frontier = False):
		color = colors.get_color(self.grid[y][x])
		startx, starty = Tile.get_position(y, x)
		A = (startx, starty)
		B = (startx + Tile.main_width, starty)
		C = (startx + Tile.main_width + Tile.side_width, starty + Tile.height/2)
		D = (startx + Tile.main_width, starty + Tile.height)
		E = (startx, starty + Tile.height)
		F = (startx - Tile.side_width, starty + Tile.height/2)
		pygame.draw.polygon(self.surface, color, [A, B, C, D, E, F])
		rect = pygame.draw.aalines(self.surface, (50, 50, 50), True, [A, B, C, D, E, F], 1)
		if frontier:
			if self.tile_is_inside(y-1,x) and self.grid[y-1][x] != self.grid[y][x]:
				pygame.draw.aalines(self.surface, (255, 255, 255), True, [A, B], 1)
			if self.tile_is_inside(y+1,x) and self.grid[y+1][x] != self.grid[y][x]:
				pygame.draw.aalines(self.surface, (255, 255, 255), True, [D, E], 1)
			if self.tile_is_inside(y-x%2,x+1) and self.grid[y-x%2][x+1] != self.grid[y][x]:
				pygame.draw.aalines(self.surface, (255, 255, 255), True, [B, C], 1)
			if self.tile_is_inside(y+1-x%2,x+1) and self.grid[y+1-x%2][x+1] != self.grid[y][x]:
				pygame.draw.aalines(self.surface, (255, 255, 255), True, [C, D], 1)
			if self.tile_is_inside(y-x%2,x-1) and self.grid[y-x%2][x-1] != self.grid[y][x]:
				pygame.draw.aalines(self.surface, (255, 255, 255), True, [F, A], 1)
			if self.tile_is_inside(y+1-x%2,x-1) and self.grid[y+1-x%2][x-1] != self.grid[y][x]:
				pygame.draw.aalines(self.surface, (255, 255, 255), True, [E, F], 1)
		pygame.display.update(rect)

	def get_sprite(self, obj):
		if obj == 1:
			sprite = self.sprite_soldier
		else:
			sprite = self.sprite_tower
		offset = (-3, -7)
		sprite_rect = (0, 0, 40, 40)
		return sprite, offset, sprite_rect

	def draw_sprite(self, y, x):
		if self.unit[y][x] != -1:
			sprite, offset, sprite_rect = self.get_sprite(self.unit[y][x])
			pos = Tile.get_position(y,x)
			newpos = pos[0] + offset[0], pos[1] + offset[1]
			self.surface.blit(sprite, newpos, sprite_rect) 
			pygame.display.update((newpos[0],newpos[1],sprite_rect[2],sprite_rect[3]))

	#desenha o sprite e outras coisas devido ao posicionamento do mouse
	def draw_move_sprite(self, y, x):
		if y < 0 or x < 0 or y >= self.height or x >= self.width:
			return
		sprite, offset, sprite_rect = self.get_sprite(1)
		pos = Tile.get_position(y,x)
		newpos = pos[0] + offset[0], pos[1] + offset[1]
		self.surface.blit(sprite, newpos, sprite_rect) 
		pygame.display.update((newpos[0],newpos[1],sprite_rect[2],sprite_rect[3]))

	# desenha o sprite_surface em surface no tile (x,y)... offset eh um par (x,y) empirico para posicionar o sprite corretamente
	# e sprite_rect eh o retangulo do sprite no sprite_surface (a porcao do desenho que contem varios sprites)
	def update_tile(self, y, x, frontier = False):
		if y < 0 or x < 0 or y >= self.height or x >= self.width:
			return
		self.draw_tile(y, x, frontier)
		self.draw_sprite(y, x)

	def create_area(self, y, x, p, idx, fall):
		if y < 0 or x < 0 or x >= self.width or y >= self.height or p <= 0:
			return
		if randint(0, 100) < p:
			self.grid[y][x] = idx
			self.create_area(y+1,x,p-fall,idx, fall)
			self.create_area(y-1,x,p-fall,idx, fall)
			self.create_area(y,x-1,p-fall,idx, fall)
			self.create_area(y,x+1,p-fall,idx, fall)

	def mouse_posevent(self, pos_mouse):
		newpos = self.get_position(pos_mouse[1], pos_mouse[0])
		if newpos != self.current_mouse:
			self.update_tile(self.current_mouse[1]-1, self.current_mouse[0])
			self.update_tile(self.current_mouse[1], self.current_mouse[0])
			self.update_tile(self.current_mouse[1]+1, self.current_mouse[0])
			#self.update_tile(newpos[1], newpos[0])
			self.draw_move_sprite(newpos[1], newpos[0])
		self.current_mouse = newpos

	def mouse_select_event(self, pos_mouse, current_nation_index):
		pos = self.get_position(pos_mouse[1], pos_mouse[0])
		self.draw_frontier(pos[1], pos[0], current_nation_index, [])
		print str(pos[1]) + ' ' + str(pos[0])
		return

	def mouse_putunit_event(self, pos_mouse, current_nation_index):
		pos = self.get_position(pos_mouse[1], pos_mouse[0])
		x = pos[0]
		y = pos[1]
		if(self.grid[y][x] == current_nation_index):
			self.grid[y][x] = 2
			self.unit[y][x] = 1
			self.update_tile(y, x)

